// #include "util.hpp"
// #include "format.hpp"
// #include "sink.hpp"
// #include "logger.hpp"
// #include "buffer.hpp"
#include "../include/easylog.h"
#include <string.h>

//测试实用工具
void testUtil()
{
    //测试文件类，是否可以获取文件路径和创建文件路径
    std::string filename("./logs/testUtil/log.log");
    easylog::util::File::createPath(easylog::util::File::getPath(filename));
    //测试颜色类
    struct tm lt;
    time_t t = easylog::util::Date::getTime();
    localtime_r(&t, &lt);
    char now[32] = {0};
    strftime(now, 31, "%F %H:%M:%S", &lt);
    for(auto& e : easylog::util::color::_cols)
        std::cout << e.second << now << easylog::util::color::offclr() << std::endl;
}
//测试格式化器
void testFormat()
{
    std::shared_ptr<easylog::Formatter> fptr1(new easylog::Formatter("[%d{%H:%M:%S]}%m%n"));
    easylog::LogMsg msg("root", __FILE__, __LINE__, easylog::LogLevel::value::INFO, "字符解析成功");
    std::string str = fptr1->format(msg);
    std::cout << str;

    ////格式异常情况
    // std::shared_ptr<easylog::Formatter> fptr2(new easylog::Formatter("[%d{%H:%M:%S]%m%n"));
    // std::shared_ptr<easylog::Formatter> fptr3(new easylog::Formatter("[%d{%H:%M:%S]}%m%n%"));
    // std::shared_ptr<easylog::Formatter> fptr4(new easylog::Formatter("[%dabcd{%H:%M:%S]}%m%n%"));
    // std::shared_ptr<easylog::Formatter> fptr5(new easylog::Formatter("[%d{%H:%M:%S]}%q%m%n%"));
}
//测试落地方向
void testSink()
{
    //日志消息
    easylog::LogMsg msg("root", __FILE__, __LINE__, easylog::LogLevel::value::INFO, "落地方向测试");
    //日志格式化
    std::shared_ptr<easylog::Formatter> fptr(new easylog::Formatter("[%d{%H:%M:%S]}%m%n"));
    std::string str = fptr->format(msg);
    //标准输出
    easylog::LogSink::ptr stdout_ptr = easylog::SinkFactory::create<easylog::StdOutSink>();
    for(auto& e : easylog::util::color::_cols)
    {
        stdout_ptr->changeColor((easylog::util::color::color_enum)e.first);
        stdout_ptr->log(str.c_str(), str.size());
    }
    //指定文件
    easylog::LogSink::ptr file_ptr = easylog::SinkFactory::create<easylog::FileSink>("./logs/logtest.log");
    file_ptr->log(str.c_str(), str.size());
    //大小滚动文件
    easylog::LogSink::ptr rollsize_ptr = easylog::SinkFactory::create<easylog::RollBySizeSink>("./logs/size/roll-", 1024 * 1024, 3600);
    size_t cur_size = 0, count = 0;
    while(cur_size < 1024 * 1024 * 10)
    {
        std::string tmp = std::to_string(count++) + str;
        rollsize_ptr->log(tmp.c_str(), tmp.size());
        cur_size += tmp.size();
    }
    //时间滚动文件
    easylog::LogSink::ptr rolltime_ptr = easylog::SinkFactory::create<easylog::RollByTimeSink>("./logs/time/roll-", 1024, 10);
    cur_size = 0, count = 0;
    while(count < 100)
    {
        std::string tmp = std::to_string(count++) + str;
        rolltime_ptr->log(tmp.c_str(), tmp.size());
        usleep(500000);
    }
}
//测试同步日志器
void testSyncLogger()
{
    std::string logger_name = "SyncLogger";//日志器名称
    //日志格式化控制器 
    easylog::Formatter::ptr fptr(new easylog::Formatter("[%d{%H:%M:%S]}[%f:%l][%p][%c]%m%n"));
    //标准输出，指定文件，大小滚动文件
    easylog::LogSink::ptr stdout_ptr = easylog::SinkFactory::create<easylog::StdOutSink>(easylog::util::color::color_enum::light_blue);
    easylog::LogSink::ptr file_ptr = easylog::SinkFactory::create<easylog::FileSink>("./logs/logtest.log");
    easylog::LogSink::ptr rollsize_ptr = easylog::SinkFactory::create<easylog::RollBySizeSink>("./logs/size/roll-", 1024 * 1024, 3600);
    std::vector<easylog::LogSink::ptr> sinks = {stdout_ptr, file_ptr, rollsize_ptr};
    //日志器
    easylog::Logger::ptr lptr(new easylog::SyncLogger(logger_name, easylog::LogLevel::value::WARN, fptr, sinks));
    lptr->debug("%s", "同步日志器测试");
    lptr->info("%s", "同步日志器测试");
    lptr->warn("%s", "同步日志器测试");
    lptr->error("%s", "同步日志器测试");
    lptr->fatal("%s", "同步日志器测试");
    size_t cur_size = 0, count = 0;
    while(cur_size < 1024 * 1024)
    {
        lptr->fatal("同步日志器-致命错误测试-%d", count++);
        cur_size += 50;
    }
}
//测试局部日志器建造者
void testLoggerBuilder()
{
    std::unique_ptr<easylog::LoggerBuilder> builder(new easylog::LocalLoggerBuilder());
    builder->buildLoggerName("root");
    builder->buildLoggerLevel(easylog::LogLevel::value::WARN);
    builder->buildSink<easylog::StdOutSink>(easylog::util::color::red);
    builder->buildSink<easylog::FileSink>("./logs/test.log");
    builder->buildSink<easylog::RollBySizeSink>("./logs/size/roll-",1024 * 1024, 60);
    //建造日志器
    easylog::Logger::ptr lptr(builder->build());
    lptr->debug("%s", "局部日志器建造者测试");
    lptr->info("%s", "局部日志器建造者测试");
    lptr->warn("%s", "局部日志器建造者测试");
    lptr->error("%s", "局部日志器建造者测试");
    lptr->fatal("%s", "局部日志器建造者测试");
    size_t cur_size = 0, count = 0;
    while(cur_size < 1024 * 1024)
    {
        lptr->error("局部日志器建造者测试-警告错误测试-%d", count++);
        cur_size += 50;
    }
}
//测试异步缓冲区
void testBuffer()
{
    easylog::util::File::createPath("./logs");
    //写数据
    std::ofstream ofs;
    ofs.open("./logs/test.log", std::ios::binary | std::ios::app);
    char ch = 'a';
    for(int i = 0; i < 50 * 1024 * 1024; ++i)
        ofs.write(&ch, 1);
    ofs.close();
    //读数据到buffer,观察其扩容
    std::ifstream ifs("./logs/test.log", std::ios::binary);
    ifs.seekg(0, std::ios::end);//读写位置跳转到文件末尾
    size_t fsize = ifs.tellg();//获取当前读写位置相对于文件开头的相对位置
    ifs.seekg(0, std::ios::beg);
    std::string body;
    body.reserve(fsize);
    ifs.read(&body[0], fsize);
    ifs.close();
    easylog::Buffer buffer;
    for(int i = 0; i < fsize; ++i)
        buffer.push(&body[i], 1);
    //将buffer数据写入文件
    ofs.open("./logs/tmp.log", std::ios::binary | std::ios::app);
    size_t rsize = buffer.readAbleSize();
    for(int i = 0; i < rsize; ++i)
    {
        ofs.write(buffer.readBegin(), 1);
        buffer.moveReader(1);
    }
    ofs.close();
}
//测试异步日志器&异步工作器
void testAsyncLogger()
{
    std::unique_ptr<easylog::LoggerBuilder> builder(new easylog::LocalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildLoggerLevel(easylog::LogLevel::value::WARN);
    //设置生产异步日志器
    builder->buildLoggerType(easylog::LoggerType::LOGGER_ASYNC);
    //测试不安全模式
    //builder->setUnsafeAsync();
    builder->buildSink<easylog::StdOutSink>(easylog::util::color::blue);
    builder->buildSink<easylog::FileSink>("./logs/async.log");
    //建造日志器
    easylog::Logger::ptr lptr(builder->build());
    lptr->debug("%s", "异步日志器测试");
    lptr->info("%s", "异步日志器测试");
    lptr->warn("%s", "异步日志器测试");
    lptr->error("%s", "异步日志器测试");
    lptr->fatal("%s", "异步日志器测试");
    size_t count = 0;
    while(count < 50 * 1000)
        lptr->error("异步日志器测试-警告错误测试-%d", count++);
}
//测试全局日志器建造者
void test_log(const std::string& logger_name)
{
    easylog::Logger::ptr logger = easylog::LoggerManager::getInstance().getLogger(logger_name);
    if(logger.get() == nullptr)
        std::cout << "日志器为空\n";
    logger->debug("%s", "全局建造者测试");
    logger->info("%s", "全局建造者测试");
    logger->warn("%s", "全局建造者测试");
    logger->error("%s", "全局建造者测试");
    logger->fatal("%s", "全局建造者测试");
    size_t count = 0;
    while(count < 30 * 1000)
        logger->error("全局建造者测试-警告错误测试-%d", count++);
}
//测试全局接口
void testGlobalInterface(const std::string& logger_name)
{
    // easylog::Logger::ptr logger = easylog::getLogger(logger_name);
    // if(logger.get() == nullptr)
    //     std::cout << "日志器为空\n";
    // logger->debug("%s", "全局接口测试");
    // logger->info("%s", "全局接口测试");
    // logger->warn("%s", "全局接口测试");
    // logger->error("%s", "全局接口测试");
    // logger->fatal("%s", "全局接口测试");
    // size_t count = 0;
    // while(count < 30 * 1000)
    //     logger->error("全局接口测试-警告错误测试-%d", count++);

    EASYLOG_LOGGER_DEBUG("%s", "全局默认日志器接口测试");
    EASYLOG_LOGGER_INFO("%s", "全局默认日志器接口测试");
    EASYLOG_LOGGER_WARN("%s", "全局默认日志器接口测试");
    EASYLOG_LOGGER_ERROR("%s", "全局默认日志器接口测试");
    EASYLOG_LOGGER_FATAL("%s", "全局默认日志器接口测试");
    size_t count = 0;
    // while(count < 30 * 1000)
    //     EASYLOG_LOGGER_ERROR("全局默认日志器接口测试-警告错误测试-%d", count++);

}
//测试全局日志器建造者 & 全局接口
void testGlobalLoggerBuilder()
{
    std::unique_ptr<easylog::LoggerBuilder> builder(new easylog::GlobalLoggerBuilder());
    builder->buildLoggerName("async_logger");
    builder->buildLoggerLevel(easylog::LogLevel::value::WARN);
    //设置生产异步日志器
    builder->buildLoggerType(easylog::LoggerType::LOGGER_ASYNC);
    builder->buildSink<easylog::StdOutSink>(easylog::util::color::red);
    //全局建造者建造后，就可以在任意位置调用
    builder->build();
    //test_log("async_logger");//测试全局日志器建造者
    testGlobalInterface("async_logger");//测试全局接口
}


int main()
{
    //testUtil();
    //testFormat();
    testSink();
    //testSyncLogger();
    //testLoggerBuilder();
    //testBuffer();
    //testAsyncLogger();
    //testGlobalLoggerBuilder();
}